package be.kdg.bombermanunlimited.client.network.packet;

import java.util.Arrays;

/**
 * Een object dat data in de vorm van een byte array bijhoudt en hierop
 * manipulatiefuncties voorziet.
 * 
 * @author Philip
 * 
 */
public class PacketData {
	// de data
	private byte[] data;

	/**
	 * maak een leeg data object
	 */
	public PacketData() {
		this(null);
	}

	/**
	 * maak een data object gebasseerd op data
	 * 
	 * @param data
	 */
	public PacketData(byte[] data) {
		if (data == null) {
			this.data = new byte[0];
		} else {
			this.data = data.clone();
		}
	}

	/**
	 * geef de data terug
	 * 
	 * @return
	 */
	public byte[] getData() {
		return data;
	}

	/**
	 * vervang de data door nieuwe data
	 * 
	 * @param data
	 */
	public void setData(byte[] data) {
		if (data == null) {
			this.data = new byte[0];
		} else {
			this.data = data.clone();
		}
	}

	/**
	 * Verwijder data vooraan
	 * 
	 * @param length
	 *            de lengte die eraf moet
	 */
	public void removeFrontData(int length) {
		// System.out.println("[PacketData] removing front: start: " + length
		// + " total size: " + data.length);
		this.data = Arrays.copyOfRange(data, length, data.length);
	}

	/**
	 * Behouw een deel van de data
	 * 
	 * @param start
	 *            de start dat bijgehouden moet worden
	 * @param length
	 *            de lengte die bijgehouden moet worden
	 */
	public void keepData(int start, int length) {
		// System.out.println("[PacketData] Keep data: start: " + length
		// + " total size: " + data.length + " end: "
		// + (start + length + 1));

		this.data = Arrays.copyOfRange(data, start, start + length + 1);
	}

	/**
	 * verwijder data op het einde
	 * 
	 * @param length
	 */
	public void removeEndData(int length) {
		// System.out.println("[PacketData] Keep data: start: 0 total size: "
		// + data.length + " end: " + (data.length - length));

		if (data.length - length > 0) {
			this.data = Arrays.copyOf(data, data.length - length);
		}
	}

	public int getDataLength() {
		return data.length;
	}

	/**
	 * haal de eerste byte eraf en geef deze terug
	 * 
	 * @return
	 */
	public byte popByte() {
		byte tmp = data[0];
		removeFrontData(1);

		return tmp;
	}

	/**
	 * haal de eerste int eraf en geef deze terug. De omzet functies byte-array
	 * -> int is zelf gemaakt en maak gebruik van Big-endian.
	 * 
	 * @return
	 */
	public int popInt() {
		int tmp = (((int) data[0] << 24) & 0xFF000000)
				| (((int) data[1] << 16) & 0x00FF0000)
				| (((int) data[2] << 8) & 0x0000FF00)
				| ((int) data[3] & 0x000000FF);

		removeFrontData(4);
		return tmp;
	}

	/**
	 * voeg een int vooraan toe, volgens Big-endian.
	 * 
	 * @param data
	 */
	public void pushFront(int data) {
		byte[] tmp = new byte[4];
		tmp[0] = (byte) (data >> 24);
		tmp[1] = (byte) (data >> 16);
		tmp[2] = (byte) (data >> 8);
		tmp[3] = (byte) (data);

		pushFront(tmp);
	}

	/**
	 * voeg data vooraan toe
	 * @param data
	 */
	public void pushFront(byte[] data) {
		byte[] tmp = new byte[this.data.length + data.length];

		for (int i = 0; i < data.length; i++) {
			tmp[i] = data[i];
		}

		for (int i = 0; i < this.data.length; i++) {
			tmp[i + data.length] = this.data[i];
		}

		this.data = tmp;
	}

	/**
	 * voeg een byte vooraan toe
	 * @param data
	 */
	public void pushFront(byte data) {
		byte[] tmp = new byte[this.data.length + 1];

		tmp[0] = data;

		for (int i = 0; i < this.data.length; i++) {
			tmp[i + 1] = this.data[i];
		}

		this.data = tmp;
	}
}
